'use strict';
var express = require('express');
var app = express();
var { ObjectId, MongoClient, GridFSBucket } = require('mongodb')
var PORT = 2333;
var bodyParser = require('body-parser');
const axios = require('axios');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

const { nanoid } = require('nanoid')

const config = require('./config.json')
const mongoUrl = config.mongoUrl

var db = new MongoClient(mongoUrl);
var connection = db.connect();

app.get('/', function (req, res) {
    res.json('this is the test page of /store');
});

//notice here, when user upload the file, uuid need to be added to the document of the uploaded file
//the size limit should be counted, while added to the total disk usage of the user who upload the file

app.post('/', async (req, res) => {
    console.log(req.query)
    connection.then(async () => {
        // let auth_res = await axios.post(config.authUrl,
        //     {
        //         sessionID: req.query.sessionID,
        //         tempid: req.query.tempid
        //     }
        // )
        // //console.log(auth_res.data)
        // if (auth_res.data == '') {
        //     return {
        //         status: 50000,
        //         info: "login fail"
        //     }
        // }
        let dbo = db.db("techtips");
        var bucket = new GridFSBucket(dbo, { bucketName: 'gridfsdownload' });
        var uploadStream = bucket.openUploadStream(nanoid(12).toString(), { metadata: { /*uuid: [auth_res.data.uuid]*/ } });
        var id = uploadStream.id;
        console.log(id)
        uploadStream.once('finish', function () {
            console.log("upload ended")
        });
        req.pipe(uploadStream);
        req.on('end', () => {
            res.send(id);
        });
    })
    // .catch((e) => {
    //     return res.send(JSON.stringify(e))
    // })
})

app.get('/myFile/:uuid', async (req, res) => {
    connection.then(async (db) => {
        let dbo = db.db("techtips");
        let whereStr = {
            "metadata.uuid": req.params.uuid.toString()
        }
        let result = await dbo.collection("gridfsdownload.files").find(whereStr).toArray()
        res.json({ "status": 20000, "result": result })
    })
})

//login will not be needed when access the file
//in production using cdn is a good idea
//buyvm with block storage may be a value efficient option

//one option to produce a link with TTL is to set a map with the help of redis
//nanoid(8) => ObjectId store in redis, a cron script need to be written to del the file in GridFS
//Whether it is a necessary to write a function of viewing all the files user loaded
//It becomes a web drive eventually... 
//TO COMPLEX

//notice it must be a binary file stream
//frontend POI

app.get('/:pid', function (req, res) {
    // if (!req.session.uuid) {
    //     return res.json({ "status": 50000, "info": "need to login" })
    // }
    connection.then(async () => {
        let dbo = db.db("techtips");
        var bucket = new GridFSBucket(dbo, { bucketName: 'gridfsdownload' });
        if (ObjectId.isValid(req.params.pid.toString())) {
            var id = ObjectId(req.params.pid.toString());
        } else {
            return res.send("objectId false")
        }
        let result = await dbo.collection('gridfsdownload.files').findOne({ _id: id })
        if (result == null) {
            return res.send("error")
        }
        var downloadStream = await bucket.openDownloadStream(id);
        downloadStream.pipe(res).on('finish', function () {
            console.log(id + ' get')
            res.end()
        });
    })
    // .catch((e) => {
    //     return res.send(JSON.stringify(e))
    // })
});

//using the delete function
//notice here, the axios method

app.delete('/', function (req, res) {
    if (!req.session.uuid) {
        return res.json({ "status": 50000, "info": "need to login" })
    }
    connection.then(async () => {
        let dbo = db.db("techtips");
        var bucket = new GridFSBucket(dbo, { bucketName: 'gridfsdownload' });
        if (ObjectId.isValid(req.body.id.toString())) {
            var id = ObjectId(req.body.id);
        } else {
            return res.send("id wrong")
        }
        let result = await dbo.collection('gridfsdownload.files').findOne({ _id: id })
        if (result == null) {
            return res.send("error")
        }
        await bucket.delete(id, async (error) => {
            if (error) res.send(error)
            res.send("ok")
        });
    }).catch((e) => {
        return res.send(JSON.stringify(e))
    })
})

app.listen(PORT, function () {
    console.log('Store service listening on port ' + PORT + '...');
});

